package yxy.game.pm2.module.matchonline;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;
import yxy.apple.logger.Logger;
import yxy.apple.util.ActiveUtil;
import yxy.apple.util.RandomStringUtility;
import yxy.apple.util.RandomUtility;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.*;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Format;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.message.*;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.NotificationHandle;
import yxy.game.pm2.module.arena.RankArena;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.godBeast.GodBeast;
import yxy.game.pm2.module.godBeast.PickedGodBeastModule;
import yxy.game.pm2.module.niubee.NiuBeeModule;
import yxy.game.pm2.module.player.PlayerHandle;

import java.util.*;

import static yxy.cherry.data.DataCenter.getAllData;


public class MatchOnlineHandle {

    protected static Logger logger = Logger.create(MatchOnlineHandle.class);


    private String code() {
        return BattleType.MATCHONLINE.name();
    }

    /**
     * 页面信息
     *
     * @return
     */
    public static MatchOnlineMessage.MatchPlayerOnlineInfoMsg.Builder getInfoMag(MatchOnlinePlayerModule module) {

        MatchOnlineMessage.MatchPlayerOnlineInfoMsg.Builder msg = MatchOnlineMessage.MatchPlayerOnlineInfoMsg.newBuilder();

        //可选武将
        int[] selectIdList = module.getSelectIdList();
        for (int i = 0; selectIdList != null && i < selectIdList.length; i++) {
            msg.addHeroList(selectIdList[i]);
        }

        //阵容信息
        FormatMessage.FormatArrary.Builder formatMsg = getFormatArraryMsg(module);
        msg.setFormat(formatMsg);

        //当前胜利次数
        int winTimes = module.getWinTimes();
        msg.setWinTimes(winTimes);

        //当前失败次数
        int failTimes = module.getFailTimes();
        msg.setFailTimes(failTimes);

        //历史胜利最高次数
        int passMaxWinTimes = module.getPassMaxWinTimes();
        msg.setPassWinMaxTimes(passMaxWinTimes);

        //当前状态     0：在匹配  1：取消匹配  2：结束状态
        int status = module.getStatus();
        msg.setStatus(status);

        return msg;
    }

    /**
     * 获取阵容信息
     *
     * @param module
     * @return
     */
    public static FormatMessage.FormatArrary.Builder getFormatArraryMsg(MatchOnlinePlayerModule module) {
        FormatMessage.FormatArrary.Builder formatMsg = FormatMessage.FormatArrary.newBuilder();
        Format format = module.getFormat();
        if (format == null) return formatMsg;

        if (format.getFu() != null) {
            addToFormatArraryMsg(format.getFu(), formatMsg, "FU");
        }
        if (format.getFm() != null) {
            addToFormatArraryMsg(format.getFm(), formatMsg, "FM");
        }
        if (format.getFd() != null) {
            addToFormatArraryMsg(format.getFd(), formatMsg, "FD");
        }
        if (format.getBu() != null) {
            addToFormatArraryMsg(format.getBu(), formatMsg, "BU");
        }
        if (format.getBm() != null) {
            addToFormatArraryMsg(format.getBm(), formatMsg, "BM");
        }
        if (format.getBd() != null) {
            addToFormatArraryMsg(format.getBd(), formatMsg, "BD");
        }
        return formatMsg;
    }

    /**
     * 封装每个武将信息
     *
     * @param id
     * @param formatMsg
     */
    public static void addToFormatArraryMsg(String id, FormatMessage.FormatArrary.Builder formatMsg, String position) {
        //根据id找到对应武将信息，封装信息
        FighterModule fighterModule = getMonsterFighterModuleList(Integer.parseInt(id));
        FormatMessage.HeroJson.Builder heroJson = FormatMessage.HeroJson.newBuilder();
        heroJson.setId(Integer.parseInt(id));
        heroJson.setPosition(position);
        heroJson.setHeroid(fighterModule.getHeroId());
        heroJson.setStar(fighterModule.getStarlv());
        heroJson.setStage(fighterModule.getStage());
        heroJson.setLevel(fighterModule.getLevel());
        heroJson.setPower(fighterModule.getTotalPower());
        formatMsg.addHeroJson(heroJson);
    }


    /**
     * 在线玩家pvp 怪物信息
     *
     * @param id
     * @return
     */
    public static FighterModule getMonsterFighterModuleList(int id) {
        RMap<String, FighterModule> rMap = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client().getMap("INIT:matchonline");
        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(rMap.get(String.valueOf(id)));
        FighterModule fighterModule = JSON.parseObject(jsonObject.toString(), new TypeReference<>() {
        });
        return fighterModule;
    }


    /**
     * 选择武将确认
     *
     * @param module
     * @param selectHeroId
     * @param response
     */
    public void selectHero(MatchOnlinePlayerModule module, String selectHeroId, MatchOnlineMessage.MatchPlayerOnlineSelectHeroResponse.Builder response) {
        //保存队伍信息
        saveFormat(module, selectHeroId);

        module.initSelectHeroList();

        module.set();

        int[] selectIdList = module.getSelectIdList();

        //可选武将信息
        for (int i = 0; i < selectIdList.length; i++) {
            response.addHeroList(selectIdList[i]);
        }

        //阵容信息
        FormatMessage.FormatArrary.Builder formatMsg = getFormatArraryMsg(module);
        response.setFormat(formatMsg);

    }

    private void saveFormat(MatchOnlinePlayerModule module, String selectHeroId) {
        Format format = module.getFormat();
        if (format == null) format = new Format();
        if (format.getFu() == null) {
            format.setFu(selectHeroId);
            module.setFormat(format);
            return;
        }
        if (format.getFm() == null) {
            format.setFm(selectHeroId);
            module.setFormat(format);
            return;
        }
        if (format.getFd() == null) {
            format.setFd(selectHeroId);
            module.setFormat(format);
            return;
        }
        if (format.getBu() == null) {
            format.setBu(selectHeroId);
            module.setFormat(format);
            return;
        }
        if (format.getBm() == null) {
            format.setBm(selectHeroId);
            module.setFormat(format);
            return;
        }
        if (format.getBd() == null) {
            format.setBd(selectHeroId);
            module.setFormat(format);
            return;
        }
    }


    /**
     * 保存队伍
     *
     * @param module
     */
    public void saveForamt(MatchOnlinePlayerModule module, FormatMessage.FormatArrary formatMsg) {
        List<FormatMessage.HeroJson> heroJsonList = formatMsg.getHeroJsonList();

        Format format = new Format();

        for (int i = 0; i < heroJsonList.size(); i++) {
            FormatMessage.HeroJson heroJson = heroJsonList.get(i);

            if (heroJson.getPosition().equals("FU")) {
                format.setFu(String.valueOf(heroJson.getId()));
                continue;
            }

            if (heroJson.getPosition().equals("FM")) {
                format.setFm(String.valueOf(heroJson.getId()));
                continue;

            }

            if (heroJson.getPosition().equals("FD")) {
                format.setFd(String.valueOf(heroJson.getId()));
                continue;

            }

            if (heroJson.getPosition().equals("BU")) {
                format.setBu(String.valueOf(heroJson.getId()));
                continue;

            }

            if (heroJson.getPosition().equals("BM")) {
                format.setBm(String.valueOf(heroJson.getId()));
                continue;

            }

            if (heroJson.getPosition().equals("BD")) {
                format.setBd(String.valueOf(heroJson.getId()));
                continue;
            }
        }

        module.setFormat(format);
        module.set();
    }

    /**
     * 战斗主逻辑
     *
     * @param moduleA
     * @param moduleB
     * @param playerCodeA
     * @param playerCodeB
     * @throws Exception
     */
    public void battleResponseExecute(MatchOnlinePlayerModule moduleA, MatchOnlinePlayerModule moduleB, String playerCodeA, String playerCodeB) throws Exception {
        BattleHandle battleHandle = new BattleHandle();

        BattleModule battleModule = BattleModule.create(playerCodeA);
        battleModule.setType(BattleType.MATCHONLINE);
        battleModule.setCode(code());

        // 玩家的team
        TeamModule teamA = teamPlayer(playerCodeA, moduleA.getFormat());
        battleModule.setTeamA(teamA);

        // 玩家的team
        TeamModule teamB = teamPlayer(playerCodeB, moduleB.getFormat());
        battleModule.setTeamB(teamB);

        Team team_a = teamA.team(true);
        Team team_b = teamB.team(false);
        team_a.setTeam对手(team_b);
        team_b.setTeam对手(team_a);

        // 处理战斗
        battleHandle.battleExecute(battleModule, team_a, team_b, 20);
        int round = battleModule.getRound();

        boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

        //todo 胜利的就记录胜利次数，当胜利次数大于等于12次，结算，失败次数大于等于三次也结算，发放奖励，通知玩家
        HashMap<String, Collection<PackageMessage.Item>> map;
        //20轮次  两边都算输
        if (round >= 20) {
            map = allBattleFailLogic(moduleA, moduleB);
        } else {
            map = isWin ? battleLogic(moduleA, moduleB) : battleLogic(moduleB, moduleA);
        }

        String code = String.format("matchonlineRec%s%s", DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss")), RandomStringUtility.randomAlpha(4));
        BattleRecord battleRecord = battleModule.saveRecord(code, 1);
        BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
        builder.setPlayback(battleHandle.playback(battleModule));           //战斗记录
        int resultA = battleModule.getBattleResult().getNumber();           //左侧战果
        int resultB = battleModule.getBattleResult().getOppositeNumber();   //右侧战果

        //通知玩家战斗结果和奖励
        Collection<PackageMessage.Item> rewardForA = map.get("rewardForA");
        Collection<PackageMessage.Item> rewardForB = map.get("rewardForB");

        //通知玩家
        MatchOnlineMessage.MatchPlayerOnlineInfoMsg.Builder msgA = getInfoMag(moduleA);
        MatchOnlineMessage.MatchPlayerOnlineInfoMsg.Builder msgB = getInfoMag(moduleB);
        new NotificationHandle().MatchOnlineResultNotification(playerCodeA, builder, resultA, rewardForA, msgA);
        new NotificationHandle().MatchOnlineResultNotification(playerCodeB, builder, resultB, rewardForB, msgB);

        //保存录像
        {
            MatchOnlineRecord record = new MatchOnlineRecord();

            MatchOnlineRecord.RecordPlayerInfo infoA = new MatchOnlineRecord.RecordPlayerInfo();
            PlayerBean playerBeanA = PlayerBean.get(playerCodeA);
            infoA.setPlayerName(playerBeanA.getName());
            infoA.setHead(playerBeanA.getHead());
            infoA.setHeadFrame(playerBeanA.getHeadframe());
            infoA.setPlayerCode(playerCodeA);
            record.setInfoA(infoA);

            MatchOnlineRecord.RecordPlayerInfo infoB = new MatchOnlineRecord.RecordPlayerInfo();
            PlayerBean playerBeanB = PlayerBean.get(playerCodeB);
            infoB.setPlayerName(playerBeanB.getName());
            infoB.setHead(playerBeanB.getHead());
            infoB.setHeadFrame(playerBeanB.getHeadframe());
            infoB.setPlayerCode(playerCodeB);
            record.setInfoB(infoB);

            record.setWin(isWin);
            record.setDate(DateTime.now());
            record.setBattleResult(battleModule.getBattleResult());
            record.getRecordCodes().add(battleRecord.getCode());
            record.setCode(code);
            MatchOnlineRecord.add(playerCodeA, record);
            if (round < 20) {
                record.setWin(!isWin);
            }
            MatchOnlineRecord.add(playerCodeB, record);
        }
    }

    private HashMap<String, Collection<PackageMessage.Item>> allBattleFailLogic(MatchOnlinePlayerModule moduleA, MatchOnlinePlayerModule moduleB) {
        HashMap<String, Collection<PackageMessage.Item>> map = new HashMap<>();
        moduleA.setStatus(1);//取消匹配
        moduleB.setStatus(1);//取消匹配

        moduleA.setFailTimes(moduleB.getFailTimes() + 1);
        moduleB.setFailTimes(moduleB.getFailTimes() + 1);

        //结算发奖励
        if (moduleA.getFailTimes() >= MatchOnlinePlayerModule.failMaxTimes) {
            //发奖励
            matchonlinevicreward data = DataCenter.getData(moduleA.getWinTimes()+ 1, matchonlinevicreward.class);
            if (data != null) {
                Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
                new CurrencyHandle().addCurrency(moduleA.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                map.put("rewardForB", items);
            }
            moduleA.reset(2);
        }

        if (moduleB.getFailTimes() >= MatchOnlinePlayerModule.failMaxTimes) {
            //发奖励
            matchonlinevicreward data = DataCenter.getData(moduleB.getWinTimes()+ 1, matchonlinevicreward.class);
            if (data != null) {
                Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
                new CurrencyHandle().addCurrency(moduleB.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                map.put("rewardForB", items);
            }
            moduleB.reset(2);
        }

        moduleA.set();
        moduleB.set();
        return map;
    }


    /**
     * 胜利的就记录胜利次数，当胜利次数大于等于12次，结算，失败次数大于等于三次也结算，发放奖励，通知玩家
     *
     * @param moduleA
     * @param moduleB
     */
    public HashMap<String, Collection<PackageMessage.Item>> battleLogic(MatchOnlinePlayerModule moduleA, MatchOnlinePlayerModule moduleB) {
        HashMap<String, Collection<PackageMessage.Item>> map = new HashMap<>();

        moduleA.setStatus(1);//取消匹配
        moduleB.setStatus(1);//取消匹配

        moduleA.setWinTimes(moduleA.getWinTimes() + 1);
        if (moduleA.getPassMaxWinTimes() < moduleA.getWinTimes()) {
            moduleA.setPassMaxWinTimes(moduleA.getWinTimes());
        }

        //胜利发20元宝(只在固定的时间段里面发)
        if (moduleA.getWinTimes() < MatchOnlinePlayerModule.winMaxTimes) {
            DateTime now = DateTime.now();
            DateTime time12_00 = ActiveUtil.time12_00(now);
            DateTime time13_00 = ActiveUtil.time13_00(now);
            DateTime time20_00 = ActiveUtil.time20_00(now);
            DateTime time21_00 = ActiveUtil.time21_00(now);
            if ((now.isBefore(time13_00) && now.isAfter(time12_00)) || (now.isBefore(time21_00) && now.isAfter(time20_00))) {
                Currencies rewards = new Currencies(Currency.create(CurrencyType.CT_元宝, -1, MatchOnlinePlayerModule.winRewardNum));
                new CurrencyHandle().addCurrency(moduleA.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                map.put("rewardForA", items);
            }
        }

        //结算发奖励
        if (moduleA.getWinTimes() >= MatchOnlinePlayerModule.winMaxTimes) {
            //发奖励
            matchonlinevicreward data = DataCenter.getData(moduleA.getWinTimes()+ 1, matchonlinevicreward.class);
            if (data != null) {
                Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
                new CurrencyHandle().addCurrency(moduleA.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                map.put("rewardForA", items);
            }
            moduleA.reset(2);
        }

        //结算发奖励
        moduleB.setFailTimes(moduleB.getFailTimes() + 1);
        if (moduleB.getFailTimes() >= MatchOnlinePlayerModule.failMaxTimes) {
            //发奖励
            matchonlinevicreward data = DataCenter.getData(moduleB.getWinTimes()+ 1, matchonlinevicreward.class);
            if (data != null) {
                Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
                new CurrencyHandle().addCurrency(moduleB.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                map.put("rewardForB", items);
            }
            moduleB.reset(2);
        }

        moduleA.set();
        moduleB.set();
        return map;
    }


    /**
     * 跟机器人战斗逻辑
     *
     * @param isWin
     * @param module
     * @return
     */
    public HashMap<String, Collection<PackageMessage.Item>> battleLogicWithMachine(Boolean isWin, MatchOnlinePlayerModule module) {
        HashMap<String, Collection<PackageMessage.Item>> map = new HashMap<>();
        module.setStatus(1);//取消匹配

        //胜利
        if (isWin) {
            module.setWinTimes(module.getWinTimes() + 1);
            if (module.getPassMaxWinTimes() < module.getWinTimes()) {
                module.setPassMaxWinTimes(module.getWinTimes());
            }

            //胜利发20元宝(只在固定的时间段里面发)
            if (module.getWinTimes() < MatchOnlinePlayerModule.winMaxTimes) {
                DateTime now = DateTime.now();
                DateTime time12_00 = ActiveUtil.time12_00(now);
                DateTime time13_00 = ActiveUtil.time13_00(now);
                DateTime time20_00 = ActiveUtil.time20_00(now);
                DateTime time21_00 = ActiveUtil.time21_00(now);
                if ((now.isBefore(time13_00) && now.isAfter(time12_00)) || (now.isBefore(time21_00) && now.isAfter(time20_00))) {
                    Currencies rewards = new Currencies(Currency.create(CurrencyType.CT_元宝, -1, MatchOnlinePlayerModule.winRewardNum));
                    new CurrencyHandle().addCurrency(module.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                    Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                    map.put("rewardForA", items);
                }

            }

            //结算发奖励
            if (module.getWinTimes() >= MatchOnlinePlayerModule.winMaxTimes) {
                //发奖励
                matchonlinevicreward data = DataCenter.getData(module.getWinTimes()+ 1, matchonlinevicreward.class);
                if (data != null) {
                    Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
                    new CurrencyHandle().addCurrency(module.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                    Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                    map.put("rewardForA", items);
                }
                module.reset(2);
            }

        }
        //失败
        if (!isWin) {
            module.setFailTimes(module.getFailTimes() + 1);
            if (module.getFailTimes() >= MatchOnlinePlayerModule.failMaxTimes) {
                //发奖励
                matchonlinevicreward data = DataCenter.getData(module.getWinTimes()+ 1, matchonlinevicreward.class);
                if (data != null) {
                    Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
                    new CurrencyHandle().addCurrency(module.getPlayerCode(), CCReason.在线玩家匹配, rewards);
                    Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(rewards);
                    map.put("rewardForA", items);
                }
                module.reset(2);
            }
        }

        module.set();
        return map;

    }


    /**
     * 封装team信息
     *
     * @param playerCode
     * @param format
     * @return
     */
    private TeamModule teamPlayer(String playerCode, Format format) {
        TeamModule team = new TeamModule();

        Map<Position, String> map = formatHeros(format);

        //战力
        long totalPower = 0;

        Set<Map.Entry<Position, String>> entrySet = map.entrySet();
        // 武将
        for (Map.Entry<Position, String> entry : entrySet) {
            Position position = entry.getKey();
            String id = entry.getValue();
            FighterModule fighterModule = getFighterModule(Integer.parseInt(id));
            team.addfighter(position, fighterModule);
            totalPower += fighterModule.getTotalPower();
        }

        // 神器
        NiuBeeModule niubee = NiuBeeModule.get(playerCode);
        WeaponModule weapon = WeaponModule.create(format.getNb(), niubee.getLevel(), niubee.getRefineLevel(), niubee.getSoulLevel(), niubee.getSkillLevel());
        team.setWeapon(weapon);

        //神兽
        PickedGodBeastModule godBeastModule = PickedGodBeastModule.get(playerCode);
        for (GodBeast godBeast : godBeastModule.getGbs().values()) {
            //选择上阵的那只
            if (godBeast.isBattle() && godBeast.getSkillLevel() > 0) {
                PokemonMoudle therion = new PokemonMoudle();
                Map<String, therionskill> allData = DataCenter.getAllData(therionskill.class);
                therionskill target = null;
                for (therionskill therionskill : allData.values()) {
                    if (therionskill.getType() == godBeast.getType() && therionskill.getLevel() == godBeast.getSkillLevel()) {
                        target = therionskill;
                        break;
                    }
                }
                therion.setId(godBeast.getCode());
                therion.setSkillGroupId(target.getSkillid()[0]);//主动技能
                team.setPokemonMoudle(therion);
                break;
            }
        }

        // 信息
        PlayerBean playerBean = PlayerBean.get(playerCode);
        team.setName(playerBean.getName());
        team.setHead(playerBean.getHead());
        team.setLevel(playerBean.getLevel());
        team.setPower(totalPower);
        team.setPlayerCode(playerCode);
        return team;
    }


    /**
     * 上阵的队伍信息
     *
     * @param format
     * @return
     */
    public Map<Position, String> formatHeros(Format format) {
        HashMap<Position, String> map = new HashMap<>();
        if (format.getFu() != null) {
            map.put(Position.FU, format.getFu());
        }
        if (format.getFm() != null) {
            map.put(Position.FM, format.getFm());
        }
        if (format.getFd() != null) {
            map.put(Position.FD, format.getFd());
        }
        if (format.getBu() != null) {
            map.put(Position.BU, format.getBu());
        }
        if (format.getBm() != null) {
            map.put(Position.BM, format.getBm());
        }
        if (format.getBd() != null) {
            map.put(Position.BD, format.getBd());
        }
        return map;
    }

    public Format getMechineFormat(int[] heroId) {
        Format format = new Format();
        for (int i = 0; i < heroId.length; i++) {
            if (format.getFu() == null) {
                format.setFu(String.valueOf(heroId[i]));
                continue;
            }
            if (format.getFm() == null) {
                format.setFm(String.valueOf(heroId[i]));
                continue;

            }
            if (format.getFd() == null) {
                format.setFd(String.valueOf(heroId[i]));
                continue;

            }
            if (format.getBu() == null) {
                format.setBu(String.valueOf(heroId[i]));
                continue;

            }
            if (format.getBm() == null) {
                format.setBm(String.valueOf(heroId[i]));
                continue;

            }
            if (format.getBd() == null) {
                format.setBd(String.valueOf(heroId[i]));
                continue;
            }
        }
        return format;
    }


    /**
     * 跟机器人打斗 (从自己胜场+-范围内的机器人列表找出其中一个，不能是自己的机器人)
     *
     * @param playerCode
     * @param module
     * @param queuePlayerInfo
     */
    public void battleWithMechineResponseExecute(String playerCode, MatchOnlinePlayerModule module, QueuePlayerInfo queuePlayerInfo) {

        int winTimes = module.getWinTimes();
        WorldRankMatchOnline rank = WorldRankMatchOnline.getRank();
        RList<MatchOnlineMachine> listA = MatchOnlineMachine.get(winTimes - 1);
        RList<MatchOnlineMachine> listB = MatchOnlineMachine.get(winTimes);
        RList<MatchOnlineMachine> listC = MatchOnlineMachine.get(winTimes + 1);
        List<MatchOnlineMachine> list = new ArrayList<>();
        if (listA != null && listA.size() != 0) list.addAll(listA.readAll());
        if (listB != null && listB.size() != 0) list.addAll(listB.readAll());
        if (listC != null && listC.size() != 0) list.addAll(listC.readAll());

        //人机匹配失败 最多30秒提示玩家匹配失败(保险)
        if (DateTime.now().isAfter(queuePlayerInfo.getUpdateTime().plusSeconds(30))) {
            rank.delete(playerCode);
            module.setStatus(1);
            module.set();
            logger.info("not machine");
            return;
        }

        //如果20秒，则从预先的人机列表找玩家
        if (DateTime.now().isAfter(queuePlayerInfo.getUpdateTime().plusSeconds(20))) {

            Map<String, matchonlinebot> allData = DataCenter.getAllData(matchonlinebot.class);
            for (matchonlinebot value : allData.values()) {
                if (value.getLoserate() == module.getFailTimes() && module.getWinTimes() == module.getWinTimes()) {
                    RankArena rankArena = RankArena.getRank(playerCode);
                    ArrayList<RankEntry> top = (ArrayList<RankEntry>) rankArena.top(rankArena.topSize());
                    RankEntry rankEntry = top.get(RandomUtility.nextInt(0, top.size()));
                    if (rankEntry != null) {
                        MatchOnlineMachine machine = new MatchOnlineMachine();
                        machine.setPlayerCode(rankEntry.getKey());
                        Format format = getMechineFormat(value.getHeroid());
                        machine.setFormat(format);
                        list.add(machine);
                        break;
                    }
                }
            }
        }


        //如果机器人里面只有一个 判断是不是自己 是自己则重新放回队列继续匹配
        if (list.size() == 1 && list.get(0).getPlayerCode().equals(playerCode)) {
            RedissonClient client = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client();
            RQueue<QueuePlayerInfo> queue = client.getQueue(MatchOnlinePlayerModule.redisQuene);
            queue.add(queuePlayerInfo);
            return;
        }

        //匹配机器人,从list里面找一个不是自己的去打斗
        Collections.shuffle(list);
        MatchOnlineMachine machine = null;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getPlayerCode().equals(playerCode)) continue;
            machine = list.get(i);
            break;
        }

        //找不到人,重新放队列
        if (machine == null) {
            RedissonClient client = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client();
            RQueue<QueuePlayerInfo> queue = client.getQueue(MatchOnlinePlayerModule.redisQuene);
            queue.add(queuePlayerInfo);
            return;
        }

        //打斗返回战斗信息
        rank.delete(playerCode);

        BattleHandle battleHandle = new BattleHandle();
        BattleModule battleModule = BattleModule.create(playerCode);
        battleModule.setType(BattleType.MATCHONLINE);
        battleModule.setCode(code());

        // 玩家的team
        TeamModule teamA = teamPlayer(playerCode, module.getFormat());
        battleModule.setTeamA(teamA);

        // 玩家的team
        TeamModule teamB = teamPlayer(machine.getPlayerCode(), machine.getFormat());
        battleModule.setTeamB(teamB);

        Team team_a = teamA.team(true);
        Team team_b = teamB.team(false);
        team_a.setTeam对手(team_b);
        team_b.setTeam对手(team_a);

        // 处理战斗
        battleHandle.battleExecute(battleModule, team_a, team_b, 20);
        boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

        //todo 胜利的就记录胜利次数，当胜利次数大于等于12次，结算，失败次数大于等于三次也结算，发放奖励，通知玩家
        HashMap<String, Collection<PackageMessage.Item>> map = battleLogicWithMachine(isWin, module);

        String code = String.format("matchonlineRec%s%s", DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss")), RandomStringUtility.randomAlpha(4));
        BattleRecord battleRecord = battleModule.saveRecord(code, 1);
        BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
        builder.setPlayback(battleHandle.playback(battleModule));           //战斗记录
        int resultA = battleModule.getBattleResult().getNumber();           //左侧战果

        //通知玩家战斗结果和奖励
        Collection<PackageMessage.Item> rewardForA = map.get("rewardForA");
        //通知玩家
        MatchOnlineMessage.MatchPlayerOnlineInfoMsg.Builder msgA = getInfoMag(module);
        new NotificationHandle().MatchOnlineResultNotification(playerCode, builder, resultA, rewardForA, msgA);

        //保存录像
        {
            MatchOnlineRecord record = new MatchOnlineRecord();

            MatchOnlineRecord.RecordPlayerInfo infoA = new MatchOnlineRecord.RecordPlayerInfo();
            PlayerBean playerBeanA = PlayerBean.get(playerCode);
            infoA.setPlayerName(playerBeanA.getName());
            infoA.setHead(playerBeanA.getHead());
            infoA.setHeadFrame(playerBeanA.getHeadframe());
            infoA.setPlayerCode(playerCode);
            record.setInfoA(infoA);

            MatchOnlineRecord.RecordPlayerInfo infoB = new MatchOnlineRecord.RecordPlayerInfo();
            PlayerBean playerBeanB = PlayerBean.get(machine.getPlayerCode());
            infoB.setPlayerName(playerBeanB.getName());
            infoB.setHead(playerBeanB.getHead());
            infoB.setHeadFrame(playerBeanB.getHeadframe());
            infoB.setPlayerCode(machine.getPlayerCode());
            record.setInfoB(infoB);

            record.setWin(isWin);
            record.setDate(DateTime.now());
            record.setBattleResult(battleModule.getBattleResult());
            record.getRecordCodes().add(battleRecord.getCode());
            record.setCode(code);
            MatchOnlineRecord.add(playerCode, record);
        }
    }


    /**
     * 获取内存的某个武将信息
     */
    public FighterModule getFighterModule(int id) {
        RMap<String, FighterModule> rMap = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client().getMap("INIT:matchonline");
        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(rMap.get(String.valueOf(id)));
        FighterModule fighterModule = JSON.parseObject(jsonObject.toString(), new TypeReference<FighterModule>() {
        });
        return fighterModule;
    }


    /**
     * 判断是否重复
     *
     * @param format
     * @param heroId
     * @return
     */
    public boolean isRepeatHero(Format format, String heroId) {
        if (format == null) return false;
        if (format.getFu() != null && format.getFu().equals(heroId)) {
            return true;
        }
        if (format.getFm() != null && format.getFm().equals(heroId)) {
            return true;
        }
        if (format.getFd() != null && format.getFd().equals(heroId)) {
            return true;
        }
        if (format.getBu() != null && format.getBu().equals(heroId)) {
            return true;
        }
        if (format.getBm() != null && format.getBm().equals(heroId)) {
            return true;
        }
        if (format.getBd() != null && format.getBd().equals(heroId)) {
            return true;
        }
        return false;
    }


    /**
     * 获取随机武将信息
     *
     * @return
     */
    public int[] getSelectHero(MatchOnlinePlayerModule module) {
        ArrayList<Integer> selectHeroList = new ArrayList<>();
        int[] heros = new int[3];

        Format format = module.getFormat();
        int twentyOneHeroNum = module.getTwentyOneHeroNum();
        Map<String, matchonlinedata> datas = getAllData(matchonlinedata.class);
        List<SummonData> list = new ArrayList<>();
        for (matchonlinedata data : datas.values()) {
            list.add(new SummonData(data));
        }

        for (int i = 0; i < heros.length; i++) {
            SummonData one = RandomUtility.randomWeight(list);
            int maxTime = 0;
            Reward reward = null;
            //判重，以及22资质最多两个
            while (true) {
                reward = one.getReward();
                if (isRepeatHero(format, String.valueOf(reward.id)) || (reward.quality > 21 && twentyOneHeroNum >= 2) || selectHeroList.contains(reward.id)) {
                    maxTime++;
                    one = RandomUtility.randomWeight(list);
                } else {
                    break;
                }

                //保护措施  当大于20次重复也不管了
                if (maxTime > 20) {
                    break;
                }
            }

            if (reward.quality > 21) {
                twentyOneHeroNum++;
            }

            heros[i] = reward.id;
            selectHeroList.add(reward.id);
        }

        return heros;
    }

    /**
     * 战斗记录
     *
     * @param playerCode
     * @param response
     */
    public void record(String playerCode, MatchOnlineMessage.MatchPlayerOnlineRecordResponse.Builder response) {
        List<MatchOnlineRecord> records = MatchOnlineRecord.get(playerCode);
        for (MatchOnlineRecord record : records) {
            MatchOnlineRecord.RecordPlayerInfo infoA = record.getInfoA();
            MatchOnlineRecord.RecordPlayerInfo infoB = record.getInfoB();
            if (infoA == null || infoB == null) continue;
            MatchOnlineMessage.MatchPlayerRecord.Builder builder = MatchOnlineMessage.MatchPlayerRecord.newBuilder();

            builder.setRecord(record.getCode());
            builder.setDate(record.getDate().getMillis());
            int result = record.getBattleResult().getNumber();

            if (!record.getInfoA().getPlayerCode().equals(playerCode)) {
                result = record.getBattleResult().getOppositeNumber();   //右侧战果
            }
            builder.setResult(result);

            PlayerMessage.PlayerSimpleInfo.Builder oppoInfo = null;
            if (!record.getInfoA().getPlayerCode().equals(playerCode)) {
                oppoInfo = new PlayerHandle().playerSimpleInfo(record.getInfoA().getPlayerCode());
            } else {
                oppoInfo = new PlayerHandle().playerSimpleInfo(record.getInfoB().getPlayerCode());
            }
            builder.setOppoInfo(oppoInfo);

            response.addRecords(builder);
        }

    }

    /**
     * 战斗信息详情
     *
     * @param playerCode
     * @param code
     * @param response
     * @return
     */
    public Result recordInfo(String playerCode, String code, MatchOnlineMessage.MatchPlayerOnlineRecordInfoResponse.Builder response) {
        List<MatchOnlineRecord> list = MatchOnlineRecord.get(playerCode);
        for (MatchOnlineRecord record : list) {
            if (record.getRecordCodes().equals(code)) {
                for (String recordCode : record.getRecordCodes()) {
                    BattleRecord battleRecord = BattleRecord.getv(recordCode);
                    if (battleRecord == null) {
                        continue;
                    }
                    response.addPlayback(new BattleHandle().playback(battleRecord));
                }
            }
        }
        return Result.PlainsArenaRecordOut;// 战斗记录不存在了
    }


    // -------------------------------------------------------------------------------------------------------------------
    public class SummonData implements RandomUtility.Weight {
        private matchonlinedata data;

        private SummonData(matchonlinedata data) {
            this.data = data;
        }

        private Reward getReward() {
            List<Reward> rewards = new ArrayList<>();
            for (int i = 0; i < data.getHeroid().length; i++) {
                int id = data.getHeroid()[i];
                int weight = data.getPercent()[i];
                int quality = data.getStars();
                if (id > 0 && weight > 0) {
                    rewards.add(new Reward(id, weight, quality));
                }
            }
            return RandomUtility.randomWeight(rewards);
        }

        @Override
        public int getWeight() {
            return data.getChance();
        }
    }

    private class Reward implements RandomUtility.Weight {

        int id;
        int weight;
        int quality;

        private Reward(int id, int weight, int quality) {
            this.id = id;
            this.weight = weight;
            this.quality = quality;
        }

        @Override
        public int getWeight() {
            return weight;
        }
    }

}
